package com.wHitE.servlet;

import com.google.gson.Gson;
import com.wHitE.utils.Result;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
import org.apache.commons.fileupload2.core.FileItem;
import org.apache.commons.fileupload2.core.FileUploadException;
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

@WebServlet("/upload")
//@MultipartConfig(maxFileSize = 2 * 1024 * 1024, maxRequestSize = 5 * 2 * 1024 * 1024)
public class UploadServlet extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("上传接口初始化...");
        super.init(config);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("上传接口调用...");
        super.service(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取out对象
        PrintWriter out = resp.getWriter();

        // 初始化 object=>json 对象
        Gson gson = new Gson();

//        // 以下上传方式仅支持servlet3.0以上
//        // 注:必须需要@MultipartConfig注解
//        // 注:前端提交类型必须为 multipart/form-data
//
//        // 获取part对象
//        Part part = req.getPart("files");
//
//        // 创建uuid防止重名覆盖
//        String uuid = UUID.randomUUID().toString();
//        // 获取文件名
//        String filename = uuid + '_' + part.getSubmittedFileName();
//        System.out.println("上传文件名:" + filename);
//
//        // 获取文件存放路径(绝对路径)
//        String uploadFilePath = "/uploadFiles/images";
//        String filePath = req.getServletContext().getRealPath("/uploadFiles/images");
//        File file = new File(filePath);
//        if (!file.exists()) {
//            file.mkdirs();
//        }
//        System.out.println("文件存放路径:" + filePath);
//
//        // 上传写入文件到指定目录
//        part.write(filePath + "/" + filename);
//
//        //响应给前端
//        resp.setContentType("application/json;utf-8");
//        out.print(gson.toJson(Result.success(uploadFilePath.substring(1, uploadFilePath.length()) + "\\" + filename)));

        // 以下上传方式支持前端异步请求中请求体上传文件且支持servlet低版本(无@MultipartConfig注解的版本)
        // 注:前端提交类型必须为 multipart/form-data

        // 创建文件对象,当默认缓存空间不够时,使用此文件对象空间
        File tempFile = new File("C:\\wHitE_temp");
        if (!tempFile.exists()) {
            tempFile.mkdirs();
        }

        // 创建文件项工厂对象
        // 设置文件大小超限缓存位置
        DiskFileItemFactory factory = DiskFileItemFactory.builder().setPath("C:\\wHitE_temp").get();

        // 创建文件项处理对象并指定工厂对象
        JakartaServletFileUpload fileUpload = new JakartaServletFileUpload(factory);
        fileUpload.setHeaderCharset(StandardCharsets.UTF_8);

        // 解析request对象 老方法是直接解析request对象,2023/11/07日的今天,老方法似乎被弃用,需要先将其转换为RequestContext对象
        try {
            List<FileItem> fileItems = fileUpload.parseRequest(req);
            // 遍历解析出的文件项
            for (FileItem fileItem : fileItems) {
                // 先判断是否为普通字段显然我写这个接口不是处理普通字段的...但是还是写一下
                if (fileItem.isFormField()) {
                    // 获取普通表单项的字段名和字段值
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString(StandardCharsets.UTF_8);
                    System.out.println("表单项名称:" + name + "\n" + "表单项值" + value);
                } else {
                    // 创建uuid防止重名覆盖
                    String uuid = UUID.randomUUID().toString();
                    // 获取上传的文件文件名
                    String filename = uuid + '_' + fileItem.getName();
                    System.out.println("上传文件名:" + filename);
                    // 获取文件存放路径(绝对路径)
                    String uploadFilePath = "/uploadFiles/images";
                    String filePath = req.getServletContext().getRealPath(uploadFilePath);
                    File file = new File(filePath);
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    System.out.println("文件存放路径:" + filePath);
                    // 上传写入文件到指定目录
                    fileItem.write(Paths.get(filePath + "/" + filename));

                    //响应给前端
                    resp.setContentType("application/json;utf-8");
                    out.print(gson.toJson(Result.success(uploadFilePath.substring(1, uploadFilePath.length()) + "/" + filename)));
                }
            }
        } catch (FileUploadException e) {
            out.print(Result.error("上传出错!请检查"));
            throw new RuntimeException(e);
        } catch (Exception e) {
            out.print(Result.error("处理上传文件出错"));
            throw new RuntimeException(e);
        }

    }

    @Override
    public void destroy() {
        System.out.println("上传接口关闭...");
    }
}
